<template>
	<prevent-view :stop="props.stop">
		<view class="e-icon" @tap="clickHandler" :class="[ns.m(props.labelPos)]">
			<image class="e-icon__img" v-if="isImg" :src="name" :mode="imgMode" :style="[imgStyle, addStyle(props.customStyle)]"></image>
			<text v-else class="e-icon__icon" :class="uClasses" :style="[iconStyle, addStyle(props.customStyle)]" :hover-class="hoverClass">{{ icon }}</text>
			<!-- 这里进行空字符串判断，如果仅仅是v-if="label"，可能会出现传递0的时候，结果也无法显示 -->
			<text
				v-if="props.label !== ''"
				class="e-icon__label"
				:style="{
					color: props.labelColor,
					fontSize: addUnit(props.labelSize),
					marginLeft: props.labelPos == 'right' ? addUnit(props.space) : 0,
					marginTop: props.labelPos == 'bottom' ? addUnit(props.space) : 0,
					marginRight: props.labelPos == 'left' ? addUnit(props.space) : 0,
					marginBottom: props.labelPos == 'top' ? addUnit(props.space) : 0
				}"
			>
				{{ label }}
			</text>
		</view>
	</prevent-view>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import mpMixin from '../../libs/mixin/mpMixin';

/**
 * icon 图标
 * @description 基于字体的图标集，包含了大多数常见场景的图标。
 * @tutorial https://www.uviewui.com/components/icon.html
 * @property {String}			name			图标名称，见示例图标集
 * @property {String}			color			图标颜色,可接受主题色
 * @property {String | Number}	size			图标字体大小，单位px （默认 '16px' ）
 * @property {Boolean}			bold			是否显示粗体 （默认 false ）
 * @property {String | Number}	index			点击图标的时候传递事件出去的index（用于区分点击了哪一个）
 * @property {String}			hoverClass		图标按下去的样式类，用法同uni的view组件的hoverClass参数，详情见官网
 * @property {String}			customPrefix	自定义扩展前缀，方便用户扩展自己的图标库 （默认 'eicon' ）
 * @property {String | Number}	label			图标右侧的label文字
 * @property {String}			labelPos		label相对于图标的位置
 * @property {String | Number}	labelSize		label字体大小，单位px （默认 '15px' ）
 * @property {String}			labelColor		图标右侧的label文字颜色
 * @property {String | Number}	space			label与图标的距离，单位px （默认 '3px' ）
 * @property {String}			imgMode			图片的mode
 * @property {String | Number}	width			显示图片小图标时的宽度
 * @property {String | Number}	height			显示图片小图标时的高度
 * @property {String | Number}	top				图标在垂直方向上的定位 用于解决某些情况下，让图标垂直居中的用途  （默认 0 ）
 * @property {Boolean}			stop			是否阻止事件传播 （默认 false ）
 * @property {Object}			customStyle		icon的样式，对象形式
 * @event {Function} click 点击图标时触发
 * @event {Function} touchstart 事件触摸时触发
 * @example <e-icon name="photo" color="#2979ff" size="28"></e-icon>
 */
export default defineComponent({
	name: 'e-icon',
	mixins: [mpMixin]
});
</script>

<script lang="ts" setup>
import { computed, toRefs, onMounted } from 'vue';
// 引入图标名称，已经对应的unicode
import icons from './icons';
import { iconProps, iconEmits } from './props';
import { addUnit, addStyle } from '../../libs/utils/_utils';
import { useNamespace, useDefaultProps } from '../../libs/hooks';
import componentsProps, { type DefaultProps } from '../../libs/config/componentsProps';
import preventView from '../prevent-view/index.vue';

const { icon: iconDefaultProps } = toRefs(componentsProps);

const _props = defineProps(iconProps);
const props = useDefaultProps<DefaultProps['icon']>(_props, iconDefaultProps);
const emit = defineEmits(iconEmits);

const ns = useNamespace('icon');

const uClasses = computed(() => {
	let classes: string | string[] = [];
	classes.push(props.value.customPrefix + '-' + props.value.name);
	// 阿里，头条，百度小程序通过数组绑定类名时，无法直接使用[a, b, c]的形式，否则无法识别
	// 故需将其拆成一个字符串的形式，通过空格隔开各个类名
	//#ifdef MP-ALIPAY || MP-TOUTIAO || MP-BAIDU
	classes = classes.join(' ');
	//#endif
	return classes;
});
const iconStyle = computed(() => ({
	fontSize: addUnit(props.value.size as string),
	lineHeight: addUnit(props.value.size as string),
	fontWeight: props.value.bold ? 'bold' : 'normal',
	// 某些特殊情况需要设置一个到顶部的距离，才能更好的垂直居中
	top: addUnit(props.value.top as string),
	color: props.value.color
}));

// 判断传入的name属性，是否图片路径，只要带有"/"均认为是图片形式
const isImg = computed(() => {
	return props.value.name?.indexOf('/') !== -1;
});
const imgStyle = computed(() => ({
	width: addUnit(props.value.width || (props.value.size as string)),
	height: addUnit(props.value.height || (props.value.size as string))
}));
// 通过图标名，查找对应的图标
const icon = computed(() => {
	// 如果内置的图标中找不到对应的图标，就直接返回name值，因为用户可能传入的是unicode代码
	return icons['eicon-' + props.value.name] || props.value.name;
});
const clickHandler = (e: any) => {
	emit('click', props.value.index);
};

onMounted(() => {
	// #ifdef APP-NVUE
	// nvue通过uni的dom模块引入字体，相关文档地址如下：
	// https://uniapp.dcloud.net.cn/tutorial/nvue-api.html#dom
	const fontUrl = 'https://at.alicdn.com/t/font_2225171_8kdcwk4po24.ttf';
	const domModule = uni.requireNativePlugin('dom');
	domModule.addRule('fontFace', {
		fontFamily: 'eicon-iconfont',
		src: `url('${fontUrl}')`
	});
	// #endif
});
</script>

<style lang="scss" scoped>
@import '../../libs/theme/icon.scss';
</style>
